/**
 * All right reserved@Raygo 2022~2030
 */

package com.raygo.runner.core;

import java.util.Locale;

import com.raygo.runner.core.entity.Component;
import com.raygo.runner.core.entity.GroupInfo;
import com.raygo.runner.core.entity.GroupType;
import com.raygo.runner.core.entity.Group;
import com.raygo.runner.core.entity.Step;
import com.raygo.runner.core.result.BoolResult;

/**
 * 步骤项组执行器
 *
 * @author Raygo
 * @since 2022年5月21日
 */
public class GroupExecutor {
    /**
     * 步骤项组
     */
    private Group stepGroup;

    /**
     * 扩展信息
     */
    private GroupInfo groupInfo;

    /**
     * 构造执行器
     *
     * @param stepGroup 步骤项组
     * @param info      扩展信息
     */
    public GroupExecutor(Group stepGroup, GroupInfo info) {
        this.stepGroup = stepGroup;
        this.groupInfo = info;
    }

    /**
     * 执行组内的所有步骤
     *
     * @return 结果
     */
    public BoolResult runAllSteps() {
        BoolResult result = new BoolResult();
        try {
            // 初始化
            result = stepGroup.init();
            if (result.getCode() != 0) {
                return result;
            }

            // 分别执行每一步骤
            for (Step stepItem : stepGroup.getStepItems()) {
                runStepItem(stepItem, result);
                // 退出组中的步骤总是执行
                if (stepGroup.getType() == GroupType.EXIT) {
                    continue;
                }
                if (result.getCode() != 0) {
                    return result;
                }
            }
        } catch (Exception ex) {
            result.setCode(101010);
            result.setError("Exception:" + ex.getMessage());
        } finally {
            // 退出
            stepGroup.exit();
        }
        return result;
    }

    /**
     * 执行步骤项
     *
     * @param item   步骤
     * @param result 结果
     */
    protected void runStepItem(Step item, BoolResult result) {
        if (!item.isEnable()) {
            return;
        }

        // 获取组件的对象
        String componentKey = String.format(Locale.ROOT, "%s%d", item.getComponent(), item.getComponentIndex());
        Component component = groupInfo.getComponent(componentKey);
        if (component == null) {
            result.setCode(-101);
            result.setError("Cannot found component");
            return;
        }

        // 多次尝试执行
        int retry = item.getRetry() < 1 ? 1 : item.getRetry();
        for (int i = 0; i < retry; i++) {
            result = component.run(item.getMethod(), item.getParams());
            if (result.getCode() != 0) {
                continue;
            }

            // 不需要判断
            if (item.getJudgeString() == null) {
                break;
            }

            // 需要判断
            if (judgeResult(item.getJudgeString(), result)) {
                break;
            }
        }

        // 非关键项设置结果总是成功
        if (!item.isKey()) {
            result.setCode(0);
        }
    }

    /**
     * 判断结果
     *
     * @param judgeString 判断条件
     * @param result      结果
     * @return 成功与否
     */
    protected boolean judgeResult(String judgeString, BoolResult result) {
        return true;
    }
}
